<?php

namespace addons\yunfood\model;

use addons\epay\library\Service;
use addons\yunfood\library\Logic;
use addons\yunfood\library\ModelTrait;
use think\Exception;
use think\Model;
use think\Request;

/**
 * 订单支付模型
 */
class Payment extends Model
{
    use ModelTrait;

    // 表名,不含前缀
    protected $name = 'yunfood_payment';

    // 自动写入时间戳字段
    protected $autoWriteTimestamp = true;

    // 定义时间戳字段名
    protected $updateTime = 'updated_at';
    protected $createTime = 'created_at';

    protected $resultSetType = 'collection';

    // 订单类型
    const ORDER_TYPE_GOODS = 'goods';
    const ORDER_TYPE_FUND  = 'fund';

    public static function getOrderTypeList()
    {
        return [self::ORDER_TYPE_GOODS => __('商品'), self::ORDER_TYPE_FUND => __('余额')];
    }

    public function getOrderTypeTextAttr($value, $data)
    {
        $optionList = self::getOrderTypeList();

        return $optionList[$data['order_type']] ?? $data['order_type'];
    }

    // 渠道
    const CHANNEL_WECHAT_MP      = 'wechat-mp';
    const CHANNEL_WECHAT_MINIAPP = 'wechat-miniapp';
    const CHANNEL_ALIPAY_SCAN    = 'alipay-scan';

    public static function getChannelList()
    {
        return [
            self::CHANNEL_WECHAT_MP      => __('微信H5支付'),
            self::CHANNEL_WECHAT_MINIAPP => __('微信小程序支付'),
            self::CHANNEL_ALIPAY_SCAN    => __('支付宝扫码支付')
        ];
    }

    public function getChannelTextAttr($value, $data)
    {
        $optionList = self::getChannelList();

        return $optionList[$data['channel']] ?? $data['channel'];
    }

    // 状态
    const STATUS_WAIT    = 1;
    const STATUS_DONE    = 2;
    const STATUS_INVALID = 3;

    public static function getStatusList()
    {
        return [
            self::STATUS_WAIT    => __('待支付'),
            self::STATUS_DONE    => __('已支付'),
            self::STATUS_INVALID => __('已失效')
        ];
    }

    public function getStatusTextAttr($value, $data)
    {
        $optionList = self::getStatusList();

        return $optionList[$data['status']] ?? $data['status'];
    }

    public function getPaymentResult()
    {
        list($type, $method) = explode('-', $this->channel);
        $params = [
            'type'      => $type,  // wechat、alipay
            'orderid'   => $this->trade_no,
            'title'     => $this->goods_name,
            'amount'    => $this->goods_amount,
            'method'    => $method, // web、wap、app、scan、pos、mp，miniapp
            'auth_code' => null,
            'notifyurl' => (Request::instance())->domain() . '/index.php/addons/yunfood/web/' . $type . 'Callback',
            'returnurl' => '',
        ];
        if (in_array($method, ['mp', 'miniapp'])) {
            $source = null;
            if ($method === 'mp') {
                $source = UserAuth::SOURCE_MP;
            } elseif ($method === 'miniapp') {
                $source = UserAuth::SOURCE_MINI;
            }
            if (! $userAuth = UserAuth::get(['user_id' => $this->user_id, 'source' => $source])) {
                throw new Exception('获取微信用户信息失败');
            }
            $params['openid'] = $userAuth->openid;
        }
        $paymentData = Service::submitOrder($params);

        return [
            'order_type'   => $this->order_type,
            'order_no'     => $this->order_no,
            'channel'      => $this->channel,
            'payment_no'   => $this->payment_no,
            'payment_data' => $paymentData
        ];
    }

    public static function getPaymentData($orderType, $orderData, $channel)
    {
        $payment = null;
        if ($orderData->payment_no) {
            if ($payment = Payment::get(['payment_no' => $orderData->payment_no])) {
                if ($payment->channel != $channel || $payment->created_at < time() - 300) {
                    $payment = null;
                } else {
                    $payment->status = Payment::STATUS_INVALID;
                    $payment->save();
                }
            }
        }
        if ($payment === null) {
            $payment = new Payment();
            $payment->payment_no = Logic::generateBusinessNo('payment_no');
            $payment->order_type = $orderType;
            $payment->order_no = $orderData->order_no;
            $payment->trade_no = Logic::generateBusinessNo('trade_no');
            $payment->user_id = $orderData->user_id;
            $payment->goods_name = ($orderType == self::ORDER_TYPE_FUND ? $orderData->fund_pack_name : '菜品')
                . '-' . $orderData->order_no;
            $payment->channel = $channel;
        }
        $payment->goods_amount = $orderData->payment;
        if ($orderType == self::ORDER_TYPE_GOODS) {
            $payment->goods_amount -= $orderData->balance;
        }
        $payment->user_ip = request()->ip();
        $payment->request_time = time();
        $payment->status = Payment::STATUS_WAIT;
        $payment->save();

        return $payment;
    }
}
